# -*- coding:utf-8 -*-

from selenium import webdriver

import importlib
import pickle
import time
import os

import platform

import yaml


def get_config():
    with open("config.yml", 'r', encoding='utf-8') as f:
        config = yaml.full_load(f)
    return config


def clean_exit():
    ff.quit()
    if errs != []:
        exit(1)
    else:
        exit()


def load_cookies(path):
    with open("cookies/" + path, 'rb') as f:
        cookies = pickle.load(f)
    return cookies


def work(task):
    name = task['name']
    url = task['url']

    # visit the site
    logs.append("   first get")
    print(logs[-1])
    ff.get(url)
    time.sleep(5)

    # load cookies
    if task.__contains__('cookie'):
        cookies = load_cookies(task['cookie'])
        logs.append("   load cookies")
        print(logs[-1])
        for cookie in cookies:
            ff.add_cookie(cookie)
        logs.append("   second get")
        print(logs[-1])
        ff.get(url)
        time.sleep(5)

    # manual operation
    if task.__contains__('manual'):
        try:
            manual = importlib.import_module('manual.' + task['manual'])
            logs.append("   call manual operation")
            print(logs[-1])
            manual.main(ff)
            logs.append("   third get")
            print(logs[-1])
            ff.get(url)
            time.sleep(5)
        except Exception as e:
            logs.append("   warning, failed manual operation with exception:")
            print(logs[-1])
            logs.append("   " + str(e))
            print(logs[-1])

    # click button(or something)
    if task.__contains__('click'):
        try: # may just have signed, so just throw warning
            button_xpath = task['click']
            element = ff.find_element_by_xpath(button_xpath)
            logs.append("   click '%s'" % (element.get_attribute('outerHTML')))
            print(logs[-1])
            element.click()
            time.sleep(5)
        except Exception as e:
            logs.append("   warning, fail to click '%s'" % (button_xpath))
            print(logs[-1])
    # get the flag to return
    flag_xpath = task['return']
    element = ff.find_element_by_xpath(flag_xpath)
    flag = element.get_attribute('innerHTML')
    logs.append("   flag is '%s'" % (flag))
    print(logs[-1])
    if config['debug']:
        pass
    return


logs = [] # to record brief infomation and to be written in signer.log
errs = [] # to record errors and to be written in error.log
full = [] # to record all infomation when config.debug=true


# load config
config = get_config()
logs.append("[Config] debug mode is " + str(config['debug']))
print(logs[-1])

# prepare webdriver
ff_options = webdriver.firefox.options.Options()

if platform.platform().find("centos") != -1: # in CentOS, use virtual display
    os.system("killall firefox") # temporarily...
    from pyvirtualdisplay import Display
    display = Display(visible=0, size=(800, 600))
    display.start()
elif not config['debug']:
    ff_options.add_argument('--headless') # other platform, just headless

ff = webdriver.Firefox(options=ff_options)


if __name__ == '__main__':
    # mark a date
    with open("signer.log", 'a', encoding='utf-8') as f:
        f.write(time.asctime())
        f.write("\n")
    try: # write signer.log any time, and write error.log only when error occurs
        for task in config['tasks']:
            try:
                logs.append("[Start] task '%s'" % (task['name']))
                print(logs[-1])
                work(task)
                logs.append("[End] task '%s' finishes successfully" % (task['name']))
                print(logs[-1])
            except Exception as e:
                logs.append("[Error] an error occurs in task '%s'" % (task['name']))
                print(logs[-1])
                errs.append(time.asctime())
                errs.append(str(e))
                print(errs[-1])
            finally:
                ff.delete_all_cookies()
                logs.append("[Clear] deleted all cookies")
                print(logs[-1])
    except Exception as e:
        errs.append(time.asctime())
        errs.append("[Fatal] " + str(e))
        print(errs[-1])
        os.system("killall firefox") # in case of out-of-control process
        logs.append("[Clear] killed all process")
        print(logs[-1])
    finally:
        if errs != []:
            with open("error.log", 'a', encoding='utf-8') as f:
                f.write('\n'.join(errs))
        logs.append('\n') # two empty lines between days
        with open("signer.log", 'a', encoding='utf-8') as f:
            f.write('\n'.join(logs))
        if config['debug']:
            pass # TBD
        clean_exit()
